#include "bo3d.h"

// create a new instance of Ogre::Root
BBDECL Ogre::Root* __stdcall o_newRoot(const char* plugins, const char* config, const char* logfile, bool manual)
{
	Ogre::Root* r;
	try
	{
		if(manual == true)
		{
			r = new Ogre::Root();
		}
		else
		{
			r = new Ogre::Root(Ogre::String(plugins), Ogre::String(config), Ogre::String(logfile));
		}
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return r;
}

// Checks for saved video/sound/etc settings. 
BBDECL bool __stdcall o_restoreConfig(Ogre::Root* root)
{
	bool result = false;
	try
	{
		result = root->restoreConfig();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return result;
}

// Displays a dialog asking the user to choose system settings.
BBDECL bool __stdcall o_showConfigDialog(Ogre::Root* root)
{
	bool result = false;
	try
	{
		result = root->showConfigDialog();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return result;
}

// Initialises the renderer.
BBDECL Ogre::RenderWindow* __stdcall o_initialise(Ogre::Root* root, bool autoCreateWindow, const char* windowTitle, const char* customCapabilities)
{
	Ogre::RenderWindow* win;

	try
	{
		win = root->initialise(autoCreateWindow, Ogre::String(windowTitle), Ogre::String(customCapabilities));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getFullDescription() << std::endl;
	}

	return win;
}

// Shuts down the system manually.
BBDECL void __stdcall o_freeRoot(Ogre::Root* root)
{
	Ogre::MaterialManager::getSingleton().destroyAllResourcePools();
	root->shutdown();
}

// Saves the details of the current configuration. 
BBDECL void __stdcall o_saveConfig(Ogre::Root* root)
{
	try
	{
		root->saveConfig();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Retrieve a pointer to the render system by the given name. 
BBDECL Ogre::RenderSystem* __stdcall o_getRenderSystemByName(Ogre::Root* root, const char* name)
{
	Ogre::RenderSystem* rs;
	try
	{
		rs = root->getRenderSystemByName(Ogre::String(name));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return rs;
}

// Sets the rendering subsystem to be used. 
BBDECL void __stdcall o_setRenderSystem(Ogre::Root* root, Ogre::RenderSystem* rs)
{
	try
	{
		root->setRenderSystem(rs);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Creates a new rendering window. 
BBDECL Ogre::RenderWindow* __stdcall o_createRenderWindow(Ogre::Root* root, const char* name, int width, int height, bool fullscreen, const char* miscParams)
{
	Ogre::RenderWindow* win;
	Ogre::NameValuePairList misc;
	Ogre::String mP = Ogre::String(miscParams);
	try
	{
		if(mP.length() > 1)
		{
			Ogre::StringVector sv	= Ogre::StringUtil::split(mP, "|");
			int c = 0;
			for(Ogre::StringVector::iterator i = sv.begin(); i != sv.end(); i++)
			{
				Ogre::String par = *i; i++;
				Ogre::String val = *i;
			
				misc[par] = val;
			}

			win = root->createRenderWindow(name, width, height, fullscreen, &misc);
		}
		else
		{
			win = root->createRenderWindow(name, width, height, fullscreen);
		}
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getFullDescription() << std::endl;
	}

	return win;
}

// Manually load a Plugin contained in a DLL / DSO. 
BBDECL void __stdcall o_loadPlugin(Ogre::Root* root, const char* plugin)
{
	try
	{
		root->loadPlugin(Ogre::String(plugin));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Create a SceneManager  instance based on scene type support.
BBDECL Ogre::SceneManager* __stdcall o_createSceneManager(Ogre::Root* root, Ogre::SceneTypeMask typeMask, const char* instanceName)
{
	Ogre::SceneManager* scm;
	try
	{
		scm = root->createSceneManager(typeMask, Ogre::String(instanceName));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return scm;
}

// Render one frame, with custom frame time information. 
BBDECL bool __stdcall o_renderOneFrame(Ogre::Root* root, float timeSinceLastFrame)
{
	bool result = false;
	try
	{
		result = root->renderOneFrame(Ogre::Real(timeSinceLastFrame));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return result;
}

// Retrieve a pointer to the currently selected render system. 
BBDECL Ogre::RenderSystem* __stdcall o_getRenderSystem(Ogre::Root* root)
{
	Ogre::RenderSystem* rs;

	try
	{
		rs = root->getRenderSystem();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return rs;
}

BBDECL void __stdcall o_messagePump()
{
	Ogre::WindowEventUtilities::messagePump();
}

BBDECL void __stdcall o_addFrameListener(Ogre::Root* root, Ogre::FrameListener* newListener)
{
	try
	{
		root->addFrameListener(newListener);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

BBDECL void __stdcall callBMX()
{
}